# LeetCode 1124、表现良好的最长时间段

# 一、题目描述

给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。

我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。

所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。

请你返回「表现良好时间段」的最大长度。

示例 1:

输入:hours = [9,9,6,0,6,6,9] 输出:3 解释:最长的表现良好时间段是 [9,9,6]。

示例 2:

输入:hours = [6,6,6] 输出:0

提示:

  • 1 <= hours.length <= 10^4
  • 0 <= hours[i] <= 16

# 二、题目解析

# 三、参考代码

// https://leetcode.cn/problems/longest-well-performing-interval/
class Solution {
    public int longestWPI(int[] hours) {
        // 记录当前子数组的长度
        // 表示 表现良好时间段 的最大长度
        int maxInterval = 0;

        // 哈希表中记录每个 非零 前缀和 的 第一次 出现的 下标
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();

        // preSum 表示前缀和
        // 它是一个变量,一直迭代
        int preSum = 0;

        for (int i = 0; i < hours.length; i++) {
            
            // 如果 hours > 8 
            // 则 preSum 加 1,否则 preSum 减 1
            preSum += hours[i] > 8 ? 1 : -1;

            // 如果 preSum > 0
            // 表明从数组索引为 0 的位置出发到索引为 i 的位置
            // [ 0 , i ] 区间所有元素和大于 0
            if (preSum > 0) {

                // 从数组索引为 0 的位置出发到索引为 i 的位置组成的子数组就是 表现良好时间段 
                maxInterval = i + 1;

            // 如果某一个位置的前缀和 preSum 不大于 0
            } else{

                // putIfAbsent() 方法会先判断指定的键(key)是否存在
                // 不存在则将键/值对插入到 HashMap 中
                // key 如果存在就不存储
                map.putIfAbsent(preSum, i);

                // 查找[ 0 , i ] 这个区间当中,是否已经保存了前缀和为 preSum - 1 的情况
                // 如果有这种情况,表示某个区间 [ 0 , j ] 的元素和为 preSum - 1
                if (map.containsKey(preSum - 1)) {

                    // 区间 [ 0 , j ] 的元素和为 preSum - 1
                    int j =  map.get(preSum - 1);

                    // 此时,我们访问的是索引为 i 的元素,整个区间是这样的
                    // [ 0 , ... , j , ... , i , .... ]
                    // [ 0 , i ] 区间里面的所有元素和是 preSum
                    // [ 0 , j ] 区间里面的所有元素和是 preSum - 1
                    // ( j , i ] 区间里面的所有元素和是 1 ,是 表现良好的时间段
                    int interval = i - j;

                    // 更新最值
                    maxInterval = Math.max(maxInterval, interval);

                }
            }   
        }

        // 返回结果
        return maxInterval;
    }
}